package cz.muni.fi.pa165.languageschool.dao.impl;

import cz.muni.fi.pa165.languageschool.Lecture;
import cz.muni.fi.pa165.languageschool.Student;
import cz.muni.fi.pa165.languageschool.dao.StudentDao;
import cz.muni.fi.pa165.languageschool.utils.Authority;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * StudentDao implementation using JPA
 *
 * @author Michal Fučík (395624) michal.fuca.fucik(at)gmail.com, Milos Petrovic
 * (256790) mpetrovickg(at)gmail.com
 */
public class StudentDaoImpl implements StudentDao {

    final static Logger log = LoggerFactory.getLogger(StudentDaoImpl.class);

    private EntityManager entityManager;

    public StudentDaoImpl() {
    }

    public StudentDaoImpl(EntityManager em) {
        if (em == null) {
            throw new NullPointerException("Argument em was null");
        }
        this.entityManager = em;
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public List<Student> getAllStudents() {
        log.info("***** DAO Student - getAllStudents");
        TypedQuery<Student> tq = entityManager.createQuery(
                "SELECT s FROM Student s", Student.class);
        return tq.getResultList();
    }

    @Override
    public void createStudent(Student student) {
        log.info("***** DAO Student - createStudent");
        if (student == null) {
            throw new NullPointerException("Argument student cannot be null.");
        }

        entityManager.persist(student);
    }

    @Override
    public Student getStudent(Long id) {
        log.info("***** DAO Student - getStudent: {}", id);
        Student res = null;
        if (id == null) {
            throw new NullPointerException("Passed argument id was null");
        }

        res = entityManager.find(Student.class, id);

        return res;
    }

    @Override
    public void updateStudent(Student student) {
        log.info("***** DAO Student - updateStudent: {}", student);
        if (student == null) {
            throw new NullPointerException("Argument student cannot be null.");
        }

        Student stdb = entityManager.find(Student.class, student.getId());
        if (stdb == null) {
            throw new IllegalArgumentException("Passed student doesn't exist in database");
        }

        stdb.setFirstName(student.getFirstName());
        stdb.setLastName(student.getLastName());
        stdb.setUsername(student.getUsername());
        stdb.setAuthority(Authority.ROLE_USER);
        stdb.setPassword(student.getPassword());
        stdb.setEnabled(true);

        Lecture ldb = null;

        List<Lecture> resLec = new ArrayList<>();
        for (Lecture l : student.getEnrolledLectures()) {
            ldb = entityManager.find(Lecture.class, l.getId());
            if (ldb != null) {
                resLec.add(ldb);
            }
        }
        stdb.setEnrolledLectures(resLec);
        entityManager.persist(stdb);
    }

    @Override
    public void deleteStudent(Student student) {
        log.info("***** DAO Student - deleteStudent: {}", student);
        if (student == null) {
            throw new NullPointerException("Argument student cannot be null.");
        }

        Student std = entityManager.find(Student.class, student.getId());
        if (std == null) {
            throw new IllegalArgumentException("Passed student doesn't exist in database");
        }

        entityManager.remove(std);
    }

    @Override
    public Student findByUsername(String username) {
        log.info("***** DAO Student - findByusername: {}", username);
        Student res = null;
        if (username == null) {
            throw new NullPointerException("Passed argument id was null");
        }

        TypedQuery<Student> tq = entityManager.createQuery(
                "SELECT s FROM Student s WHERE s.username LIKE ?1", Student.class).setParameter(1, username);

        if (!tq.getResultList().isEmpty()) {
            res = tq.getResultList().get(0);
            log.debug("***** DAO Student - lecturer found: {}", res);
        } else {
            res = null;
            log.debug("***** DAO Student - lecturer NOT found: {}", res);
        }
        return res;
    }
}
